package org.ne.springboot.utils.PaperHandleUtils.AbstractTranslateCheckUtils;

import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.ne.springboot.utils.PaperHandleUtils.PaperContentCheckUtils.SparkClient;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author qyq
 * @description 摘要翻译检测工具类 - 优化版本
 *
 *
 * wey修改于
 * @since 2025/11/28
 */


@Slf4j
public class TranslateCheckUtils {

    // 常量定义
    private static final Logger logger = Logger.getLogger(TranslateCheckUtils.class.getName());

    private static final String ABSTRACT_CN = "摘要";
    private static final String ABSTRACT_EN = "Abstract";
    private static final String KEYWORDS_EN_PREFIX = "Key";
    private static final String KEYWORDS_CN_PREFIX = "关键词：";

    // 异常信息常量
    private static final Map<String, String> EXCEPTIONS = Map.of(
            "AbstractNotFound", "未找齐摘要以及对应翻译，请检查格式及内容是否正确",
            "returnMsgNotFormated", "返回值未严格符合格式要求，请重试",
            "fileEmpty", "文件不能为空",
            "jsonParseError", "AI返回数据格式不正确，请重试"
    );

    // 报告标题和字段名常量
    private static final String REPORT_TITLE = "摘要翻译检测报告";
    private static final String SECTION_TITLE_PATTERN = "第%d处";
    private static final String CHINESE_TEXT_PREFIX = "中文原文：";
    private static final String ENGLISH_TEXT_PREFIX = "英文原文：";
    private static final String ERROR_MSG_PREFIX = "错误原因：";
    private static final String SUGGESTION_PREFIX = "建议改正：";

    // AI请求相关常量
    private static final String AI_PROMPT = "作为专业的论文审批教授，针对每句中文判断中文摘要的英文翻译是否准确，以严格JSON格式返回，除json内容外无其他内容，并且json内容外无标点，无数字，无字符，其中包含字段chinese_text为翻译不正确的中文原文内容,english_text为chinese_text对应的英文原文，msg字段用来表示翻译不正确的原因，ans字段表示纠正后的英文翻译\n";
    private static final String AI_SUCCESS_STATUS = "success";
    private static final String AI_ANSWER_KEY = "answer";
    private static final String AI_MESSAGE_KEY = "message";

    /**
     * 查找文档中的摘要标题位置
     */
    public static List<Integer> findAbstractHeadings(XWPFDocument docx) {
        List<Integer> headList = new ArrayList<>();
        List<XWPFParagraph> paragraphs = docx.getParagraphs();

        for (int i = 0; i < paragraphs.size() && headList.size() < 2; i++) {
            String text = normalizeText(paragraphs.get(i).getText());

            if (ABSTRACT_CN.equals(text) || ABSTRACT_EN.equals(text)) {
                headList.add(i);
                logger.info("找到摘要位置: " + i + ", 文本: " + text);
            }
        }
        return headList;
    }

    /**
     * 从摘要位置提取文本直到关键词
     */
    private static AbstractExtractionResult extractTextFromAbstract(int startIndex, XWPFDocument docx) {
        StringBuilder text = new StringBuilder();
        boolean foundKeywords = false;
        List<XWPFParagraph> paragraphs = docx.getParagraphs();

        for (int i = startIndex; i < paragraphs.size(); i++) {
            XWPFParagraph paragraph = paragraphs.get(i);
            String paragraphText = paragraph.getText();
            text.append(paragraphText).append("\n");

            if (isKeywordsParagraph(paragraph, i, paragraphs)) {
                foundKeywords = true;
                break;
            }
        }

        return new AbstractExtractionResult(text.toString(), foundKeywords);
    }

    /**
     * 判断段落是否为关键词段落
     */
    private static boolean isKeywordsParagraph(XWPFParagraph paragraph, int currentIndex,
                                               List<XWPFParagraph> allParagraphs) {
        String text = paragraph.getText();
        List<XWPFRun> runs = paragraph.getRuns();

        return !runs.isEmpty() &&
                (text.startsWith(KEYWORDS_EN_PREFIX) || text.startsWith(KEYWORDS_CN_PREFIX)) &&
                (currentIndex > 0);
    }

    /**
     * 生成检测报告文档
     */
    public static XWPFDocument generateReport(String aiResponse) throws IOException {
        XWPFDocument document = new XWPFDocument();

        try {
            addReportTitle(document);
            JSONArray jsonData = parseAIResponse(aiResponse);
            addReportContent(document, jsonData);

        } catch (JsonParseException e) {
            logger.log(Level.WARNING, "JSON解析失败，生成错误报告", e);
            document = createErrorDocument(e.getMessage());
        } catch (Exception e) {
            logger.log(Level.SEVERE, "生成报告时发生未知错误", e);
            document = createErrorDocument(EXCEPTIONS.get("returnMsgNotFormated"));
        }

        return document;
    }

    /**
     * 解析AI响应，支持对象和数组格式
     */
    private static JSONArray parseAIResponse(String response) throws JsonParseException {
        if (response == null || response.trim().isEmpty()) {
            throw new JsonParseException("AI响应为空");
        }

        String jsonText = extractJsonContent(response);

        try {
            // 尝试解析为JSONObject
            if (jsonText.trim().startsWith("{")) {
                JSONObject jsonObject = new JSONObject(jsonText);
                return new JSONArray().put(jsonObject);
            }
            // 尝试解析为JSONArray
            else if (jsonText.trim().startsWith("[")) {
                return new JSONArray(jsonText);
            } else {
                throw new JsonParseException("JSON格式不正确: 应以'{'或'['开头");
            }
        } catch (JSONException e) {
            throw new JsonParseException("JSON语法错误: " + e.getMessage());
        }
    }

    /**
     * 从文本中提取JSON内容
     */
    private static String extractJsonContent(String text) {
        int start = text.indexOf('[');
        int end = text.lastIndexOf(']');

        if (start != -1 && end != -1 && end > start) {
            return text.substring(start, end + 1);
        }

        start = text.indexOf('{');
        end = text.lastIndexOf('}');

        if (start != -1 && end != -1 && end > start) {
            return text.substring(start, end + 1);
        }

        return text;
    }

    /**
     * 添加报告标题
     */
    private static void addReportTitle(XWPFDocument document) {
        XWPFParagraph heading = document.createParagraph();
        XWPFRun headingRun = heading.createRun();
        headingRun.setText(REPORT_TITLE);
        headingRun.setBold(true);
        headingRun.setFontSize(20);
    }

    /**
     * 添加报告内容
     */
    private static void addReportContent(XWPFDocument document, JSONArray jsonData) {
        for (int i = 0; i < jsonData.length(); i++) {
            JSONObject item = jsonData.getJSONObject(i);
            addReportSection(document, item, i + 1);
        }

        if (jsonData.isEmpty()) {
            addNoIssuesSection(document);
        }
    }

    /**
     * 添加报告章节
     */
    private static void addReportSection(XWPFDocument document, JSONObject item, int sectionNumber) {
        // 添加章节标题
        addSectionTitle(document, sectionNumber);

        // 添加内容段落
        addContentParagraph(document, CHINESE_TEXT_PREFIX, item.optString("chinese_text", ""));
        addContentParagraph(document, ENGLISH_TEXT_PREFIX, item.optString("english_text", ""));
        addContentParagraph(document, ERROR_MSG_PREFIX, item.optString("msg", ""));
        addContentParagraph(document, SUGGESTION_PREFIX, item.optString("ans", ""));
    }

    /**
     * 添加章节标题
     */
    private static void addSectionTitle(XWPFDocument document, int sectionNumber) {
        XWPFParagraph subHeading = document.createParagraph();
        XWPFRun subHeadingRun = subHeading.createRun();
        subHeadingRun.setText(String.format(SECTION_TITLE_PATTERN, sectionNumber));
        subHeadingRun.setBold(true);
        subHeadingRun.setFontSize(16);
    }

    /**
     * 添加内容段落
     */
    private static void addContentParagraph(XWPFDocument document, String prefix, String content) {
        if (content != null && !content.isEmpty()) {
            XWPFParagraph paragraph = document.createParagraph();
            paragraph.createRun().setText(prefix + content);
        }
    }

    /**
     * 添加无问题提示
     */
    private static void addNoIssuesSection(XWPFDocument document) {
        XWPFParagraph paragraph = document.createParagraph();
        paragraph.createRun().setText("未发现翻译问题，摘要翻译质量良好。");
    }

    /**
     * 创建错误文档
     */
    private static XWPFDocument createErrorDocument(String errorMessage) throws IOException {
        XWPFDocument document = new XWPFDocument();
        XWPFParagraph errorPara = document.createParagraph();
        errorPara.createRun().setText("检测报告生成失败 - " + errorMessage);
        return document;
    }

    /**
     * 主要检测逻辑
     */
    public static XWPFDocument check(HttpServletResponse response, MultipartFile file, String model) throws IOException {
        // 参数验证
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException(EXCEPTIONS.get("fileEmpty"));
        }

        try (InputStream is = file.getInputStream();
             XWPFDocument doc = new XWPFDocument(is)) {

            // 查找摘要位置
            List<Integer> indices = findAbstractHeadings(doc);

            if (indices.size() < 2) {
                return createErrorDocument(EXCEPTIONS.get("AbstractNotFound"));
            }

            // 提取摘要文本
            AbstractExtractionResult chineseResult = extractTextFromAbstract(indices.get(0), doc);
            AbstractExtractionResult englishResult = extractTextFromAbstract(indices.get(1), doc);

            if (!chineseResult.isFoundKeywords() || !englishResult.isFoundKeywords()) {
                System.out.println("why");
                return createErrorDocument(EXCEPTIONS.get("AbstractNotFound"));
            }

            // 调用AI处理
            String combinedText = chineseResult.getText() + englishResult.getText();
            logger.info("AI处理文本长度: " + combinedText.length());

            String aiResponse = processWithAI(combinedText, model);
            return generateReport(aiResponse);

        } catch (JSONException e) {
            logger.log(Level.WARNING, "JSON解析异常", e);
            return createErrorDocument(EXCEPTIONS.get("returnMsgNotFormated"));
        } catch (IOException e) {
            logger.log(Level.SEVERE, "文件处理异常", e);
            throw e;
        } catch (Exception e) {
            logger.log(Level.SEVERE, "检测过程中发生未知异常", e);
            return createErrorDocument("系统处理异常: " + e.getMessage());
        }
    }

    /**
     * 调用AI处理文本
     */
    private static String processWithAI(String text, String model) throws IOException {
        try {
            SparkClient sparkClient = new SparkClient();
            sparkClient.setModel(model);

            // 设置期望的响应格式
            Map<String, Object> format = new HashMap<>();
            format.put("chinese_text", "");
            format.put("english_text", "");
            format.put("msg", "");
            format.put("ans", "");
            sparkClient.setFormat(format);
            Map<String, Object> result = sparkClient.processRequest(AI_PROMPT, text);
//            log.debug("result={}", result);
            if (AI_SUCCESS_STATUS.equals(result.get("status"))) {
                Map<String, Object> answer = (Map<String, Object>) result.get(AI_ANSWER_KEY);
                return new JSONObject(answer).toString();
            } else {
                throw new IOException("AI处理失败: " + result.get(AI_MESSAGE_KEY));
            }
        } catch (Exception e) {
            logger.log(Level.ALL , "AI处理异常", e);
            throw new IOException("AI服务调用失败", e);
        }
    }

    /**
     * 翻译检测入口方法
     */
    public static XWPFDocument translate(HttpServletResponse response, MultipartFile file, String model) throws IOException {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException(EXCEPTIONS.get("fileEmpty"));
        }
        return check(response, file, model);
    }

    // 辅助方法
    private static String normalizeText(String text) {
        return text == null ? "" : text.replace("\n", "").replace("\t", "").replace(" ", "");
    }

    // 内部类：摘要提取结果
    private static class AbstractExtractionResult {
        private final String text;
        private final boolean foundKeywords;

        public AbstractExtractionResult(String text, boolean foundKeywords) {
            this.text = text;
            this.foundKeywords = foundKeywords;
        }

        public String getText() { return text; }
        public boolean isFoundKeywords() { return foundKeywords; }
    }

    // 自定义异常类
    private static class JsonParseException extends Exception {
        public JsonParseException(String message) {
            super(message);
        }

        public JsonParseException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}


//package org.ne.springboot.utils.PaperHandleUtils.AbstractTranslateCheckUtils;
//
//import jakarta.servlet.http.HttpServletResponse;
//import org.apache.poi.xwpf.usermodel.XWPFDocument;
//import org.apache.poi.xwpf.usermodel.XWPFParagraph;
//import org.apache.poi.xwpf.usermodel.XWPFRun;
//
//import java.io.*;
//import java.net.URLEncoder;
//import java.nio.charset.StandardCharsets;
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.logging.Level;
//import java.util.logging.Logger;
//import org.json.JSONArray;
//import org.json.JSONObject;
//import org.ne.springboot.utils.PaperHandleUtils.PaperContentCheckUtils.SparkClient;
//import org.springframework.stereotype.Component;
//import org.springframework.web.multipart.MultipartFile;
//
//
///**
// * @author qyq
// */
//public class TranslateCheckUtils {
//
//    //divide_docx_by_heading_1
//    public static List<Integer> divideDocxByHeading1(XWPFDocument docx) {
//        List<Integer> headList = new ArrayList<>();
//
//        for (int i = 0; i < docx.getParagraphs().size(); i++) {
//            if (headList.size() == 2) {
//                break;
//            }
//
//            XWPFParagraph paragraph = docx.getParagraphs().get(i);
//            String text = paragraph.getText().replace("\n", "").replace("\t", "").replace(" ", "");
//
//            if (text.equals("摘要") || text.equals("Abstract")) {
//                headList.add(i);
//            }
//        }
//        return headList;
//    }
//
//    //get_text_from_abstract_2_key
//    public static Object[] getTextFromAbstractToKey(int index, XWPFDocument docx) {
//        StringBuilder text = new StringBuilder();
//        boolean found = false;
//        List<XWPFParagraph> paragraphs = docx.getParagraphs();
//        for (int i = index; i < paragraphs.size(); i++) {
//            XWPFParagraph paragraph = paragraphs.get(i);
//            text.append(paragraph.getText()).append("\n");
//
//            List<XWPFRun> runs = paragraph.getRuns();
//            if (!runs.isEmpty() &&
//                    (paragraph.getText().startsWith("Key") || paragraph.getText().startsWith("关键词：")) &&
//                    runs.get(0).isBold() &&
//                    (i > 0 && paragraphs.get(i - 1).getRuns().isEmpty())) {
//                found = true;
//                break;
//            }
//        }
//        return new Object[]{text.toString(), found};
//    }
//
//    //def output(text, out_path)
//    public static XWPFDocument output(String text) throws IOException {
//        // Create a new Word document
//        XWPFDocument out = new XWPFDocument();
//
//        // Add main heading "摘要翻译检测报告"
//        XWPFParagraph heading = out.createParagraph();
//        XWPFRun headingRun = heading.createRun();
//        headingRun.setText("摘要翻译检测报告");
//        headingRun.setBold(true);
//        headingRun.setFontSize(20);
//        // Approximate equivalent to Heading 0 in python-docx
//
//        int star = 0;
//        for (int i = 0; i < text.length(); i++) {
//            if (text.charAt(i) == '[') {
//                star = i;
//                break;
//            }
//        }
//        int end = text.length();
//        for (int i = text.length() - 1; i >= 0; i--) {
//            if (text.charAt(i) == ']') {
//                end = i;
//                break;
//            }
//        }
//        String jsonText = (end >= star && end < text.length()) ? text.substring(star, end + 1) : text;
//
//        Object jsonData;
//        try {
//            jsonData = new JSONObject(jsonText); // 尝试解析为对象
//            // 如果是对象，直接放入 JSONArray
//            jsonData = new JSONArray().put(jsonData); // 将整个对象放入数组
//        } catch (Exception e) {
//            try {
//                jsonData = new JSONArray(jsonText); // 回退到数组解析
//            } catch (Exception e2) {
//                throw new RuntimeException("无法解析 JSON: " + e2.getMessage(), e2);
//            }
//        }
//
//        // Parse JSON data
//        JSONArray arrayData = (jsonData instanceof JSONArray) ? (JSONArray) jsonData : new JSONArray().put(jsonData);
//
//        // Iterate through JSON data and add content to document
//        int cnt = 0;
//        for (int i = 0; i < arrayData.length(); i++) {
//            JSONObject item = arrayData.getJSONObject(i);
//
//            // Add subheading "第X处"
//            XWPFParagraph subHeading = out.createParagraph();
//            XWPFRun subHeadingRun = subHeading.createRun();
//            subHeadingRun.setText("第" + (cnt + 1) + "处");
//            subHeadingRun.setBold(true);
//            subHeadingRun.setFontSize(16); // Approximate equivalent to Heading 1 in python-docx
//            cnt++;
//
//            // Add paragraphs for Chinese text, English text, error message, and suggestion
//            XWPFParagraph chinesePara = out.createParagraph();
//            chinesePara.createRun().setText("中文原文：" + item.getString("chinese_text"));
//
//            XWPFParagraph englishPara = out.createParagraph();
//            englishPara.createRun().setText("英文原文：" + item.getString("english_text"));
//
//            XWPFParagraph errorPara = out.createParagraph();
//            errorPara.createRun().setText("错误原因：" + item.getString("msg"));
//
//            XWPFParagraph suggestionPara = out.createParagraph();
//            suggestionPara.createRun().setText("建议改正：" + item.getString("ans"));
//        }
//        return out;
//
//    }
//
//    //def abstract_translate_check_begin(path, out_path):
//    private static final Map<String, String> exceptions = new HashMap<>() {{
//        put("AbstractNotFound", "未找齐摘要以及对应翻译，请检查格式及内容是否正确");
//        put("returnMsgNotFormated", "返回值未严格符合格式要求，请重试");
//    }};
//
//    public static XWPFDocument check(HttpServletResponse httpServletResponse, MultipartFile file, String model) throws IOException {
//
//        XWPFDocument doc = null;
//        try (InputStream is = file.getInputStream()) {
//            doc = new XWPFDocument(is);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // Extract abstract indices
//        List<Integer> indices = TranslateCheckUtils.divideDocxByHeading1(doc);
//
//        if (indices.size() < 2) {
//            XWPFDocument out = new XWPFDocument();
//            XWPFParagraph para = out.createParagraph();
//            para.createRun().setText(exceptions.get("AbstractNotFound"));
//            doc.close();
//            return out;
//        }
//
//        XWPFDocument out = new XWPFDocument();
//        // Extract abstract texts
//        Object[] result1 = TranslateCheckUtils.getTextFromAbstractToKey(indices.get(0), doc);
//        Object[] result2 = TranslateCheckUtils.getTextFromAbstractToKey(indices.get(1), doc);
//        String text1 = (String) result1[0];
//        boolean flag1 = (boolean) result1[1];
//        String text2 = (String) result2[0];
//        boolean flag2 = (boolean) result2[1];
//
//        if (flag1 && flag2) {
//            // Prompt for AI
//            String prompt = "作为专业的论文审批教授，针对每句中文判断中文摘要的英文翻译是否准确，以严格JSON格式返回，除json内容外无其他内容，并且json内容外无标点，无数字，无字符，其中包含字段chinese_text为翻译不正确的中文原文内容,english_text为chinese_text对应的英文原文，msg字段用来表示翻译不正确的原因，ans字段表示纠正后的英文翻译\n";
//
////            String text = "中文："+text1+" 英文："+text2;
//            String text = text1+text2;
//
//            System.out.println(text);
//
//
//
//            SparkClient sparkClient = new SparkClient();
//            sparkClient.setModel(model);
//
//            HashMap<String, Object> format = new HashMap<>();
//            format.put("chinese_text","翻译不正确的中文原文内容");
//            format.put("english_text","The incorrect English translation of the Chinese text.");
//            format.put("msg","翻译不准确的原因说明");
//            format.put("ans","The corrected English translation.");
//            sparkClient.setFormat(format);
//
//            Map<String, Object> result = sparkClient.processRequest(prompt, text);
//            System.out.println("result = " + result);
//
//            String aiResponse = "";
//            if ("success".equals(result.get("status"))) {
//
//                Map<String, Object> answer = (Map<String, Object>) result.get("answer");
//                // 假设 answer 包含 JSON 数据，转换为字符串
//                aiResponse = new JSONObject(answer).toString();
//
//            }
////            else {
////                throw new IOException("AI 处理失败: " + result.get("message"));
////            }
//            System.out.println("aiResponse = " + aiResponse);
//            out = output(aiResponse);
//        } else {
//            XWPFParagraph para = out.createParagraph();
//            para.createRun().setText(exceptions.get("AbstractNotFound"));
//        }
//        doc.close();
//        return out;
//
//    }
//
//    public static XWPFDocument translate(HttpServletResponse httpServletResponse, MultipartFile file, String model) throws IOException {
//        if (file == null || file.isEmpty()) {
//            throw new IllegalArgumentException("文件不能为空");
//        }
//        return check(httpServletResponse, file, model);
//    }
//
//}
